import 'dart:convert' show json;

import 'package:dio/dio.dart';

class BaseResp<T> {
  int code;
  String message;
  T result;
  bool success;

  String errorDescription = "OK";
  String error = "1";

  /*factory BaseResp(jsonStr, Function buildFun) =>
      jsonStr is String ? BaseResp.fromJson(json.decode(jsonStr), buildFun) : BaseResp.fromJson(jsonStr, buildFun);*/
  factory BaseResp(jsonStr, Function buildFun){
    if(jsonStr != null) {
      if(jsonStr is Response) {
        var data = jsonStr.data;
        return data is String ? BaseResp.fromJson(json.decode(data), buildFun) : BaseResp.fromJson(data, buildFun);
      } else {
        return jsonStr is String ? BaseResp.fromJson(json.decode(jsonStr), buildFun) : BaseResp.fromJson(jsonStr, buildFun);
      }
    } else {
      return BaseResp.fromParams(code: 9999, message: "request no response", success: false);
    }
  }

  BaseResp.fromParams({this.code, this.message, this.result, this.success, this.errorDescription, this.error});
  BaseResp.fromJson(jsonRes, Function buildFun) {
    code = jsonRes['code'];
    message = jsonRes['message'];
    success = jsonRes['success']??false;
    error = jsonRes['error']??"1";
    errorDescription = jsonRes['error_description']??"OK";

    if(error == null || error.compareTo("1") == 0){
      success = true;
    }
    _check(code, message);

    /*if(buildFun != null && jsonRes['result'] != null) {
      result = buildFun(jsonRes['result']);
      if(result != null && result is CommonResult){
        CommonResult temp = result as CommonResult;
        success = temp.success;
        if(temp.errors != null && temp.errors.length > 0){
          msg = temp.errors[0];
        }
      }
    }*/
    if(buildFun != null) {
      result = buildFun(jsonRes);
    }
  }


  @override
  String toString() {
    return '{"error": ${error != null?'${json.encode(error)}':'null'},"errorDescription": ${errorDescription != null?'${json.encode(errorDescription)}':'null'},"success": $success,"result": $result}';
  }
}

class BaseRespList<T> {
  int code;
  String msg;
  List<T> result;
  String targetUrl;
  bool success;
  bool unAuthorizedRequest;
  Error error;

//  factory BaseRespList(jsonStr, Function buildFun) => jsonStr is String
//      ? BaseRespList.fromJson(json.decode(jsonStr), buildFun)
//      : BaseRespList.fromJson(jsonStr, buildFun);
  factory BaseRespList(jsonStr, Function buildFun, {String listKey = "result"}){
    if(jsonStr != null) {
      if(jsonStr is Response) {
        var data = jsonStr.data;
        return data is String ? BaseRespList.fromJson(json.decode(data), buildFun, listKey: listKey) : BaseRespList.fromJson(data, buildFun, listKey: listKey);
      } else {
        return jsonStr is String ? BaseRespList.fromJson(json.decode(jsonStr), buildFun, listKey: listKey) : BaseRespList.fromJson(jsonStr, buildFun, listKey: listKey);
      }
    } else {
      return BaseRespList.fromParams(code: 9999, msg: "request no response", success: false);
    }
  }
  BaseRespList.fromParams({this.code, this.msg, this.result, this.success, this.unAuthorizedRequest, this.error});

  BaseRespList.fromJson(jsonRes, Function buildFun, {String listKey}) {
    code = jsonRes['code'];
    msg = jsonRes['msg'];
    targetUrl = jsonRes['targetUrl'];
    success = jsonRes['success'];
    unAuthorizedRequest = jsonRes['unAuthorizedRequest'];

    _check(code, msg);

    error = jsonRes['error'] == null ? null : new Error.fromJson(jsonRes['error']);
    if((msg == null || msg.isEmpty) && (error != null && error.message != null && error.message.isNotEmpty)){
      msg = error.message;
    }
    if(buildFun != null && jsonRes[listKey] != null) {
      result = (jsonRes[listKey] as List).map<T>((ele) => buildFun(ele)).toList();
    } else {
      result = null;
    }
  }

  @override
  String toString() {
    return '{"targetUrl": ${targetUrl != null?'${json.encode(targetUrl)}':'null'},"success": $success,"unAuthorizedRequest": $unAuthorizedRequest,"result": $result,"error": $error}';
  }
}


class BaseDataListResp<T> {
  int code;
  String msg;
  ListResult<T> result;
  String targetUrl;
  bool success;
  bool unAuthorizedRequest;
  Error error;

//  factory BaseDataListResp(jsonStr, Function buildFun) => jsonStr is String
//      ? BaseDataListResp.fromJson(json.decode(jsonStr), buildFun)
//      : BaseDataListResp.fromJson(jsonStr, buildFun);

  factory BaseDataListResp(jsonStr, Function buildFun, {String listKey = "data"}){
    if(jsonStr != null) {
      if(jsonStr is Response) {
        var data = jsonStr.data;
        return data is String ? BaseDataListResp.fromJson(json.decode(data), buildFun, listKey: listKey) : BaseDataListResp.fromJson(data, buildFun, listKey: listKey);
      } else {
        return jsonStr is String ? BaseDataListResp.fromJson(json.decode(jsonStr), buildFun, listKey: listKey) : BaseDataListResp.fromJson(jsonStr, buildFun, listKey: listKey);
      }
    } else {
      return BaseDataListResp.fromParams(code: 9999, msg: "request no response", success: false);
    }
  }
  BaseDataListResp.fromParams({this.code, this.msg, this.result, this.success, this.unAuthorizedRequest, this.error});

  BaseDataListResp.fromJson(jsonRes, Function buildFun, {String listKey}) {
    code = jsonRes['code'];
    msg = jsonRes['msg'];
    targetUrl = jsonRes['targetUrl'];
    success = jsonRes['success'];
    unAuthorizedRequest = jsonRes['unAuthorizedRequest'];

    _check(code, msg);

    error = jsonRes['error'] == null ? null : new Error.fromJson(jsonRes['error']);
    if((msg == null || msg.isEmpty) && (error != null && error.message != null && error.message.isNotEmpty)){
      msg = error.message;
    }
    if(buildFun != null && jsonRes['result'] != null) {
      result = ListResult.fromJson(jsonRes['result'], buildFun, listKey: listKey);
    } else {
      result = null;
    }
  }

  @override
  String toString() {
    return '{"targetUrl": ${targetUrl != null?'${json.encode(targetUrl)}':'null'},"success": $success,"unAuthorizedRequest": $unAuthorizedRequest,"result": $result,"error": $error}';
  }
}

/// 这里可以做code和msg的处理逻辑
void _check(int code, String msg, {String error}) {}

class ListResult<T> {

  int totalCount;
  int totalPages;
  int pageSize;
  int pageIndex;
  List<T> data;

  ListResult.fromParams({this.totalCount, this.totalPages, this.pageSize, this.pageIndex});

  ListResult.fromJson(jsonRes, Function buildFun, {String listKey = "data"}) {
    if(jsonRes == null){
      return;
    }
    totalCount = jsonRes['totalCount'];
    totalPages = jsonRes['totalPages'];
    pageSize = jsonRes['pageSize'];
    pageIndex = jsonRes['pageIndex'];

    if(buildFun != null && jsonRes[listKey] != null) {
      data = (jsonRes[listKey] as List).map<T>((ele) => buildFun(ele)).toList();
    }
  }

  @override
  String toString() {
    return '{"totalCount": $totalCount,"totalPages": $totalPages,"pageSize": $pageSize,"pageIndex": $pageIndex,"data": $data}';
  }
}

class Error {

  int code;
  String details;
  String message;
  List<ValidationErrors> validationErrors;

  Error.fromParams({this.code, this.details, this.message, this.validationErrors});

  Error.fromJson(jsonRes) {
    if(jsonRes == null){
      return;
    }
    code = jsonRes['code'];
    details = jsonRes['details'];
    message = jsonRes['message'];
    validationErrors = jsonRes['validationErrors'] == null ? null : [];

    for (var validationErrorsItem in validationErrors == null ? [] : jsonRes['validationErrors']){
      validationErrors.add(validationErrorsItem == null ? null : new ValidationErrors.fromJson(validationErrorsItem));
    }
  }

  @override
  String toString() {
    return '{"code": ${code != null?'${json.encode(code)}':'null'},"details": ${details != null?'${json.encode(details)}':'null'},"message": ${message != null?'${json.encode(message)}':'null'},"validationErrors": $validationErrors}';
  }
}

class ValidationErrors {

  String message;
  List<String> members;

  ValidationErrors.fromParams({this.message, this.members});

  ValidationErrors.fromJson(jsonRes) {
    message = jsonRes['message'];
    members = jsonRes['members'] == null ? null : [];

    for (var membersItem in members == null ? [] : jsonRes['members']){
      members.add(membersItem);
    }
  }

  @override
  String toString() {
    return '{"message": ${message != null?'${json.encode(message)}':'null'},"members": $members}';
  }
}

class CommonResult {

  int result;
  bool success;
  List<String> errors;

  CommonResult.fromParams({this.result, this.success, this.errors});

  factory CommonResult(jsonStr) => jsonStr == null ? null : jsonStr is String ? new CommonResult.fromJson(json.decode(jsonStr)) : new CommonResult.fromJson(jsonStr);

  CommonResult.fromJson(jsonRes) {
    result = jsonRes['result'];
    success = jsonRes['success'];
    errors = jsonRes['errors'] == null ? null : [];

    for (var errorsItem in errors == null ? [] : jsonRes['errors']){
      errors.add(errorsItem);
    }
  }

  @override
  String toString() {
    return '{"result": $result,"success": $success,"errors": $errors}';
  }
}
